package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"things_iot_backend/auth"
	"things_iot_backend/cache"
	"things_iot_backend/config"
	"things_iot_backend/database"
	"things_iot_backend/middleware"
	"things_iot_backend/models"
	"things_iot_backend/mqtt"
	"things_iot_backend/routes"

	"github.com/gin-gonic/gin"
)

func main() {
	// 加载配置
	cfg := config.Load()

	// 初始化数据库连接
	if err := database.InitDB(cfg); err != nil {
		log.Fatalf("Failed to initialize database: %v", err)
	}

	// 初始化Redis缓存
	if err := cache.InitRedis(cfg); err != nil {
		log.Fatalf("Failed to initialize Redis: %v", err)
	}

	// 初始化JWT
	auth.InitJWT(cfg)

	// 运行数据库迁移
	if err := runMigrations(); err != nil {
		log.Fatalf("Failed to run migrations: %v", err)
	}

	// 创建默认管理员用户
	if err := createDefaultAdmin(); err != nil {
		log.Printf("Failed to create default admin: %v", err)
	}

	// 设置Gin模式
	if cfg.AppEnv == "production" {
		gin.SetMode(gin.ReleaseMode)
	} else {
		gin.SetMode(gin.DebugMode)
	}

	// 创建Gin路由器
	router := gin.New()

	// 添加中间件
	router.Use(gin.Recovery())
	router.Use(middleware.CORSMiddleware())
	router.Use(middleware.LoggerMiddleware())
	router.Use(middleware.RateLimitMiddleware())
	router.Use(middleware.ErrorHandlerMiddleware())

	// 设置路由
	routes.SetupRoutes(router, database.DB)
	routes.SetupSwagger(router)

	// 启动MQTT服务器
	mqttServer := mqtt.NewMQTTServer(cfg)
	go func() {
		if err := mqttServer.Start(); err != nil {
			log.Fatalf("Failed to start MQTT server: %v", err)
		}
	}()

	// 启动后台任务
	startBackgroundTasks()

	// 启动HTTP服务器
	go func() {
		log.Printf("Starting HTTP server on :%d", cfg.AppPort)
		if err := router.Run(":" + strconv.Itoa(cfg.AppPort)); err != nil {
			log.Fatalf("Failed to start HTTP server: %v", err)
		}
	}()

	// 等待中断信号
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	log.Println("Shutting down server...")

	// 优雅关闭
	if err := mqttServer.Stop(); err != nil {
		log.Printf("Error stopping MQTT server: %v", err)
	}

	log.Println("Server stopped")
}

// init 初始化函数
func init() {
	// 设置日志格式
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

// createDefaultAdmin 创建默认管理员用户（仅开发环境）
func createDefaultAdmin() error {
	// 检查是否已存在管理员用户
	var count int64
	if err := database.DB.Model(&models.User{}).Where("role = ?", "super_admin").Count(&count).Error; err != nil {
		return err
	}

	if count > 0 {
		return nil // 已存在管理员用户
	}

	// 创建默认管理员
	passwordHash, err := auth.HashPassword("admin123")
	if err != nil {
		return err
	}

	admin := models.User{
		Username:     "admin",
		PasswordHash: passwordHash,
		Email:        "admin@things-iot.com",
		Role:         "super_admin",
	}

	return database.DB.Create(&admin).Error
}

// runMigrations 运行数据库迁移
func runMigrations() error {
	// 创建用户表
	if err := database.DB.AutoMigrate(&models.User{}); err != nil {
		return err
	}

	// 创建设备表
	if err := database.DB.AutoMigrate(&models.Device{}); err != nil {
		return err
	}

	log.Println("Database migrations completed successfully")
	return nil
}

// healthCheck 健康检查
func healthCheck() error {
	// 检查数据库连接
	if err := database.DB.Exec("SELECT 1").Error; err != nil {
		return fmt.Errorf("database health check failed: %v", err)
	}

	log.Println("Health check passed")
	return nil
}

// startBackgroundTasks 启动后台任务
func startBackgroundTasks() {
	// 清理离线设备状态
	go func() {
		ticker := time.NewTicker(5 * time.Minute)
		defer ticker.Stop()

		for range ticker.C {
			if err := cleanOfflineDevices(); err != nil {
				log.Printf("Failed to clean offline devices: %v", err)
			}
		}
	}()

	// 处理离线设备命令队列
	go func() {
		ticker := time.NewTicker(30 * time.Second)
		defer ticker.Stop()

		for range ticker.C {
			if err := processQueuedCommands(); err != nil {
				log.Printf("Failed to process queued commands: %v", err)
			}
		}
	}()
}

// cleanOfflineDevices 清理离线设备状态
func cleanOfflineDevices() error {
	// 将长时间未更新的设备标记为离线
	threshold := time.Now().Add(-10 * time.Minute)
	if err := database.DB.Model(&models.Device{}).
		Where("status = ? AND last_seen < ?", "online", threshold).
		Update("status", "offline").Error; err != nil {
		return err
	}
	return nil
}

// processQueuedCommands 处理队列中的命令
func processQueuedCommands() error {
	// 获取所有在线设备
	var onlineDevices []models.Device
	if err := database.DB.Where("status = ?", "online").Find(&onlineDevices).Error; err != nil {
		return err
	}

	for _, device := range onlineDevices {
		// 这里可以添加命令队列处理逻辑
		// 在实际实现中，您可能需要从Redis队列中获取命令并发送给设备
		log.Printf("Processing commands for device %s", device.DeviceID)
	}

	return nil
}
